package morenoapp.components.input;

import morenoapp.components.input.*;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.JTextField;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import morenoapp.MorenoApp;
import morenoapp.model.data.MorenoAnswerFace;
import morenoapp.model.data.MorenoQuestionFace;
import morenoapp.model.data.MorenoQuestionItemFace;
import morenoapp.model.data.MorenoRespondentFace;

/**
 * 
 * @author dmitry.mamonov
 */
public class InputSingleAnswerItemTextFieldJPanel extends javax.swing.JPanel implements MorenoRespondentSelecetionListener {

    private MorenoQuestionFace question = null;
    private MorenoQuestionItemFace questionItem = null;

    /** Creates new form InputSingleAnswerItemJPanel */
    public InputSingleAnswerItemTextFieldJPanel() {
        initComponents();

        getSelector().addKeyListener(new KeyAdapter() {

            @Override
            public void keyPressed(KeyEvent e) {
                if (e.getKeyCode() == KeyEvent.VK_ENTER) {
                    MorenoRespondentFace completition = getSelector().getCompletition();
                    if (completition != null) {
                        getSelector().setText(completition.getName());
                        getSelector().transferFocus();
                    }
                }
            }
        });
    }

    public void setQuestion(MorenoQuestionFace question) {
        this.question = question;
        this.getSelector().setQuestion(question);
        this.applyMarkerText();
    }

    public void setQuestionItem(MorenoQuestionItemFace questionItem) {
        this.questionItem = questionItem;
        this.getSelector().setQuestionItem(questionItem);
        this.applyMarkerText();
    }

    public void onRespondentSelected(MorenoRespondentFace aRespondent) {
        getSelector().setRespondent(aRespondent);
    }

    private void applyMarkerText() {
        markerLabel.setText(
                (question != null ? question.getMarker() : "") +
                (questionItem != null ? questionItem.getItemNumber() : ""));
    }

    private MorenoTextFiled getSelector() {
        return (MorenoTextFiled) jTextField;
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        markerLabel = new javax.swing.JLabel();
        jTextField = new InputSingleAnswerItemTextFieldJPanel.MorenoTextFiled();

        setName("Form"); // NOI18N

        org.jdesktop.application.ResourceMap resourceMap = org.jdesktop.application.Application.getInstance(morenoapp.MorenoApp.class).getContext().getResourceMap(InputSingleAnswerItemTextFieldJPanel.class);
        markerLabel.setFont(resourceMap.getFont("markerLabel.font")); // NOI18N
        markerLabel.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING);
        markerLabel.setText(resourceMap.getString("markerLabel.text")); // NOI18N
        markerLabel.setName("markerLabel"); // NOI18N

        jTextField.setText(resourceMap.getString("jTextField.text")); // NOI18N
        jTextField.setName("jTextField"); // NOI18N

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(markerLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 42, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(jTextField, javax.swing.GroupLayout.DEFAULT_SIZE, 139, Short.MAX_VALUE))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                .addComponent(jTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addComponent(markerLabel))
        );
    }// </editor-fold>//GEN-END:initComponents
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JTextField jTextField;
    private javax.swing.JLabel markerLabel;
    // End of variables declaration//GEN-END:variables

    class MorenoTextFiled extends JTextField {

        /**
         * Шрифт для отрисовки значения не совпадающего ни с одним из выборов.
         */
        private Font plainFont;
        /**
         * Шрифт для отрисовки значения совпадающего с одним из выборов.
         */
        private Font boldFont;
        /**
         * Наиболее подходящий кандидат под введённое значение.
         */
        private MorenoRespondentFace completition = null;
        /**
         * Вопрос которому соответствует данное поле ввода.
         */
        private MorenoQuestionFace question = null;
        /**
         * Номер ответа которому соответствует данное поле ввода.
         */
        private MorenoQuestionItemFace questionItem = null;
        /**
         * Респондент которому соответствует данное поле ввода.
         */
        MorenoRespondentFace respondent = null;

        public MorenoTextFiled() {
            super();

            //Выбираем шрифты
            plainFont = getFont();
            boldFont = new Font(plainFont.getName(), Font.BOLD, plainFont.getSize());

            //Устанавливаем слушателя документа для определения того,
            //Быбран ли какой либо респондент или нет.
            this.getDocument().addDocumentListener(new DocumentListener() {

                public void insertUpdate(DocumentEvent e) {
                    changed(e);
                }

                public void removeUpdate(DocumentEvent e) {
                    changed(e);
                }

                public void changedUpdate(DocumentEvent e) {
                    changed(e);
                }

                private void changed(DocumentEvent e) {
                    final String matchString = jTextField.getText();
                    MorenoRespondentFace target = null;
                    if (!matchString.isEmpty()) {
                        for (MorenoRespondentFace respondent : MorenoApp.getApplicationData().getMorenoModelProxy().getRespondentsList()) {
                            if (respondent.getName().toLowerCase().startsWith(matchString.toLowerCase())) {
                                System.out.println("matched: " + respondent.getName()); //NOI18N
                                target = respondent;
                                break;
                            }
                        }
                    }
                    MorenoTextFiled.this.setCompletition(target);

                }
            });

            applyContextChanged();
        }

        public MorenoQuestionFace getQuestion() {
            return question;
        }

        public void setQuestion(MorenoQuestionFace question) {
            this.question = question;
            applyContextChanged();
        }

        public MorenoQuestionItemFace getQuestionItem() {
            return questionItem;
        }

        public void setQuestionItem(MorenoQuestionItemFace questionItem) {
            this.questionItem = questionItem;
            applyContextChanged();
        }

        public MorenoRespondentFace getRespondent() {
            return respondent;
        }

        public void setRespondent(MorenoRespondentFace respondent) {
            this.respondent = respondent;
            System.out.println("Current respondent: " + respondent); //NOI18N
            applyContextChanged();
        }

        /**
         * Возвращает ресмондента, если его фамилия соответствует введённому
         * тексту полностью, в пртивном случае null.
         */
        public MorenoRespondentFace getSelectedRespondent() {
            if (completition != null && getText().equals(completition.getName())) {
                return completition;
            } else {
                return null;
            }
        }

        private void setSelectedRespondent(MorenoRespondentFace aRespondent) {
            setText(aRespondent == null ? "" : aRespondent.getName());
        }

        MorenoRespondentFace getCompletition() {
            return completition;
        }

        private void setCompletition(MorenoRespondentFace completition) {
            this.completition = completition;
            applyValueChanged();
            System.out.println("completition: " + completition); //NOI18N
        }

        @Override
        //TODO merge with HintTextField
        public void paint(Graphics g) {
            //System.out.println("paint " + System.currentTimeMillis());
            String text = getText();
            if (completition != null && text.equals(completition.getName())) {
                setFont(boldFont);
            } else {
                setFont(plainFont);
            }

            super.paint(g);


            if (completition != null && completition.getName().length() > text.length()) {
                //базовая линия - для отладки
                //g.drawLine(0, baseline, getWidth(), baseline);

                int pos = g.getFontMetrics().stringWidth(text);
                int baseline = getBaseline(getWidth(), getHeight());

                g.setColor(Color.GRAY);
                g.drawString(completition.getName().substring(text.length()), pos + getInsets().left, baseline);
            }
        }

        /**
         * Вызывается в случае изменения параметров отображения.
         */
        protected void applyContextChanged() {
            if (respondent != null && question != null && questionItem != null) {
                final MorenoAnswerFace respondentAnswer = respondent.getAnswerByQuestion(question);
                MorenoRespondentFace targetRespondent = respondentAnswer.getAnswerItemByQuestionItem(questionItem).getTarget();
                setSelectedRespondent(targetRespondent);
                setEnabled(true);
            } else {
                setText("");
                setEnabled(false);
            }
        }

        /**
         * Вызывается в случае изменения значения.
         */
        protected void applyValueChanged() {
            if (respondent != null && question != null && questionItem != null) {
                MorenoRespondentFace selectedRespondent = getSelectedRespondent();
                respondent.getAnswerByQuestion(question).getAnswerItemByQuestionItem(questionItem).setTarget(selectedRespondent);
            }
        }
    }
}
